import axios from 'axios';

import { logout, getStorageInfo } from './user';
import { showErrorMessageDebounce, showErrorMessageThrottle } from './message';

import { version1 } from '../api';

// 返回 axio，详细请参考 https://github.com/axios/axios
const requestV1Instance = axios.create({
  // 超时时间 30 秒
  timeout: 30 * 1000,
  baseURL: version1,
});

const requestV2Instance = axios.create({
  // 超时时间 30 秒
  timeout: 30 * 1000,
  baseURL: '/api/',
});

const pending: any[] = []; // 声明一个数组用于存储每个请求的取消函数和axios标识
const { CancelToken } = axios;
const removePending = (config: any) => {
  const { params = {}, url, method } = config;
  for (let p = 0; p < pending.length; p += 1) {
    // 当前请求在数组中存在时执行函数体
    if (pending[p].u === `${url} ${JSON.stringify(params)}&${method}`) {
      pending[p].f(); // 执行取消操作
      pending.splice(Number(p), 1);
      break;
    }
  }
};

// 请求拦截器
function interceptors(req: any) {
  req.interceptors.request.use((request: any) => {
    const { headers, params = {}, url, method } = request;
    const token = getStorageInfo('access_token');

    headers.Authorization = token ? `Bearer ${token}` : null;
    headers['Cache-Control'] = 'no-cache';

    // 取消重复请求 在一个axios发送前执行一下取消操作
    removePending(request);
    // 新增正在请求
    request.cancelToken = new CancelToken(c => {
      // 这里的axios标识我是用请求地址&请求方式拼接的字符串
      pending.push({
        u: `${url} ${JSON.stringify(params)}&${method}`,
        f: c,
      });
    });
    return request;
  });
  // 响应拦截器
  req.interceptors.response.use(
    (response: any) => {
      // 已结束请求删除
      removePending(response.config);
      return response;
    },
    (error: any) => {
      // axios主动取消
      if (axios.isCancel(error)) {
        console.log('cancel');
        return Promise.reject(error);
      }

      if (error.response) {
        const { data, status } = error.response;
        if (status === 401) {
          // token 过期失效
          showErrorMessageThrottle('登录失效，需重新登录。');
          setTimeout(() => {
            logout();
          }, 800);
          return Promise.reject(error);
        }

        // 4** 返回的 不一定是 json 数据，只有 data 不为 null，才是返回了 json 格式
        if (data) {
          showErrorMessageDebounce(data.message || error.response.statusText);

          return Promise.reject(error);
        }

        if (String(status).substr(0, 1) === '5') {
          showErrorMessageDebounce('系统错误。');
          return Promise.reject(error);
        }

        // 所有已知错误均未被拦截
        showErrorMessageDebounce(error.response.statusText);
      } else if (error.request) {
        // 网络无连接时会立即返回错误，请求超时（默认8秒）返回错误，跨域返回错误等情况
        showErrorMessageDebounce('网络连接出问题，或者连接超时。');
      } else {
        showErrorMessageDebounce('发生了未知错误。');
      }
      // 进入catch
      return Promise.reject(error);
    },
  );
  return req;
}

const requestV2 = interceptors(requestV2Instance);
const requestV1 = interceptors(requestV1Instance);

export { requestV2, requestV1 };

export default '';
